namespace Microsoft.ServiceModel.Samples.Discovery.Protocol
{
    using System;
    using System.Net;
    using System.Globalization;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using Microsoft.ServiceModel.Samples;
    
    public sealed class ProtocolUtility
    {
        ProtocolUtility() 
        { 
        }

        static readonly DateTime DT1970 = new DateTime(1970, 1, 1);
        public static long CreateAppSequenceInstanceId()
        {
            return (long)DateTime.Now.Subtract(DT1970).TotalSeconds;
        }

        public static OutputBinding CreateMulticastOutputBinding(string udpIPv4MulticastAddress)
        {
            if (udpIPv4MulticastAddress == null)
                throw new ArgumentNullException("udpIPv4MulticastAddress");

            UdpTransportBindingElement udpBE = new UdpTransportBindingElement();
            udpBE.Multicast = true;
            
            TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement();
            textBE.MessageVersion = MessageVersion.Soap12WSAddressingAugust2004;

            CustomBinding binding = new CustomBinding(textBE, udpBE);

            return new OutputBinding(binding, new Uri(udpIPv4MulticastAddress));
        }

        public static OutputBinding CreateMulticastOutputBinding()
        {
            return CreateMulticastOutputBinding(ProtocolStrings.IPv4MulticastAddress);
        }

        public static InputBinding CreateMulticastInputBinding(string udpIPv4MulticastAddress)
        {
            if (udpIPv4MulticastAddress == null)
                throw new ArgumentNullException("udpIPv4MulticastAddress");

            UdpTransportBindingElement udpBE = new UdpTransportBindingElement();
            udpBE.Multicast = true;
            
            TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement();
            textBE.MessageVersion = MessageVersion.Soap12WSAddressingAugust2004;

            CustomBinding binding = new CustomBinding(textBE, udpBE);

            return new InputBinding(binding, new Uri(udpIPv4MulticastAddress));
        }

        public static InputBinding CreateMulticastInputBinding()
        {
            return CreateMulticastInputBinding(ProtocolStrings.IPv4MulticastAddress);
        }

        public static InputBinding CreateMulticastDuplexInputBinding(string udpIPv4MulticastAddress)
        {
            if (udpIPv4MulticastAddress == null)
                throw new ArgumentNullException("udpIPv4MulticastAddress");

            TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement();
            textBE.MessageVersion = MessageVersion.Soap12WSAddressingAugust2004;

            CustomBinding oneWayHttpBinding = new CustomBinding(
                new OneWayBindingElement(),
                textBE,
                new HttpTransportBindingElement());

            UdpTransportBindingElement udpBE = new UdpTransportBindingElement();
            udpBE.Multicast = true;

            CustomBinding oneWayUdpBinding = new CustomBinding(textBE, udpBE);

            CompositeTransportBindingElement<CustomBinding, CustomBinding> compositeTransportBE =
                new CompositeTransportBindingElement<CustomBinding, CustomBinding>(
                    oneWayHttpBinding, oneWayUdpBinding);
            
            CompositeDuplexBindingElement compositeBE = new CompositeDuplexBindingElement();

            CustomBinding binding = new CustomBinding(compositeBE, compositeTransportBE);

            return new InputBinding(binding, new Uri(udpIPv4MulticastAddress));
        }

        public static InputBinding CreateMulticastDuplexInputBinding()
        {
            return CreateMulticastDuplexInputBinding(ProtocolStrings.IPv4MulticastAddress);
        }

        public static OutputBinding CreateMulticastDuplexOutputBinding(string udpIPv4MulticastAddress, string httpClientBaseAddress)
        {
            if (udpIPv4MulticastAddress == null)
                throw new ArgumentNullException("udpIPv4MulticastAddress");
            if (httpClientBaseAddress == null)
                throw new ArgumentNullException("httpClientBaseAddress");
            

            TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement();
            textBE.MessageVersion = MessageVersion.Soap12WSAddressingAugust2004;

            CustomBinding oneWayHttpBinding = new CustomBinding(
                new OneWayBindingElement(),
                textBE,
                new HttpTransportBindingElement());

            UdpTransportBindingElement udpBE = new UdpTransportBindingElement();
            udpBE.Multicast = true;

            CustomBinding oneWayUdpBinding = new CustomBinding(textBE, udpBE);
            CompositeTransportBindingElement<CustomBinding, CustomBinding> compositeTransportBE =
                new CompositeTransportBindingElement<CustomBinding, CustomBinding>(
                    oneWayUdpBinding, oneWayHttpBinding);

            CompositeDuplexBindingElement compositeBE = new CompositeDuplexBindingElement();
            compositeBE.ClientBaseAddress = new Uri(httpClientBaseAddress);

            CustomBinding binding = new CustomBinding(compositeBE, compositeTransportBE);

            return new OutputBinding(binding, new Uri(udpIPv4MulticastAddress));
        }

        public static OutputBinding CreateMulticastDuplexOutputBinding(string udpIPv4MulticastAddress)
        {
            string hostname = Dns.GetHostEntry(string.Empty).HostName;
            string httpClientBaseAddress = string.Format(CultureInfo.InvariantCulture, 
                "http://{0}:8000/Discovery/{1}", hostname, Guid.NewGuid().ToString());

            return CreateMulticastDuplexOutputBinding(udpIPv4MulticastAddress, httpClientBaseAddress);
        }

        public static OutputBinding CreateMulticastDuplexOutputBinding()
        {
            return CreateMulticastDuplexOutputBinding(ProtocolStrings.IPv4MulticastAddress);
        }
    }
}
   
